package com.gitee.wsl.common.chart.sample.circle

import android.graphics.*
import com.gitee.wsl.common.chart.ChartEnum
import com.gitee.wsl.common.chart.adapter.DataSource
import com.gitee.wsl.common.chart.sample.AbstractCirChart
import com.gitee.wsl.common.chart.sample.circle.adapter.CircleChartAdapter
import com.gitee.wsl.android.ext.math.calcArcEndPointXY
import com.gitee.wsl.android.ui.ext.type.textHeight
import com.gitee.wsl.common.ui.draw.type.CircleType
import com.gitee.wsl.math.Math
import com.gitee.wsl.jvm.math.add
import com.gitee.wsl.jvm.math.mul
import com.gitee.wsl.jvm.math.round
import com.gitee.wsl.jvm.math.sub
import com.gitee.wsl.math.getSliceAngle
import timber.log.Timber

/**
 * @ClassName CircleChart
 * @Description 圆形图基类 <br/>
 *        注意：当为半圆时，推荐 宽应当是高的两倍。
 * @author XiongChuanLiang<br/>(xcl_168@aliyun.com)
 */

class CircleChart(val adapter: CircleChartAdapter): AbstractCirChart(adapter) {

    //数据源
    var dataSet by DataSource(adapter)

    var dataInfo = ""
    var displayType = CircleType.FULL

    //内环填充颜色
    val bgCirclePaint: Paint by lazy{
        Paint().apply {
            color = Color.rgb(148, 159, 181)
            isAntiAlias = true
        }
    }
    val fillCirclePaint: Paint by lazy{
         Paint().apply {
             color = Color.rgb(77, 83, 97)
             isAntiAlias = true
         }
    }
    val dataInfoPaint: Paint by lazy{
        Paint().apply {
            isAntiAlias = true
            textSize = 22f
            color = Color.WHITE
            textAlign = Paint.Align.CENTER
        }
    }

    //内部填充
    var isShowInnerFill = true

    //内部背景填充
    var isShowInnerBG = true

    //显示圆形箭头标示
    var isShowCap = false


    var moRadius = 0.9f
    var miRadius = 0.8f

    override fun getType(): ChartEnum.ChartType {
        return ChartEnum.ChartType.CIRCLE
    }
    
    init {
        labelPaint.apply {
            textAlign = Paint.Align.CENTER
            textSize = 36f
            color = Color.WHITE
        }

        initOffsetAngle = 180f
        offsetAngle = 180f
    }

    /**
     * 依比例绘制扇区
     *
     * @param paintArc    画笔
     * @param cirX        x坐标
     * @param cirY        y坐标
     * @param radius      半径
     * @param offsetAngle 偏移
     * @param currentAngle 当前值
     * @throws Exception 例外
     */
    protected fun drawPercent(
        canvas: Canvas, paintArc: Paint?,
        cirX: Float,
        cirY: Float,
        radius: Float,
        offsetAngle: Float,
        currentAngle: Float
    ) {
            val arcLeft: Float = Math.sub(cirX, radius)
            val arcTop: Float = Math.sub(cirY, radius)
            val arcRight: Float = Math.add(cirX, radius)
            val arcBottom: Float = Math.add(cirY, radius)
            val arcRF0 = RectF(arcLeft, arcTop, arcRight, arcBottom)
            //在饼图中显示所占比例
            canvas.drawArc(arcRF0, offsetAngle, currentAngle, true, paintArc!!)
    }

    private fun getCirY(cirY: Float, labelHeight: Float): Float {
        var txtY = cirY
        if ("" === dataInfo) {
            txtY = cirY + labelHeight / 3
        }
        return txtY
    }


    /**
     * 绘制图
     */
    protected fun drawPlot(canvas: Canvas): Boolean {
        try {

            //中心点坐标
            val cirX: Float = bodyViewport.centerX
            val cirY: Float = bodyViewport.centerY
            val radius: Float = radius
            
            
            //确定去饼图范围
            val arcLeft: Float = Math.sub(cirX, radius)
            val arcTop: Float = Math.sub(cirY, radius)
            val arcRight: Float = Math.add(cirX, radius)
            val arcBottom: Float = Math.add(cirY, radius)
            val arcRF0 = RectF(arcLeft, arcTop, arcRight, arcBottom)

            //画笔初始化
            val paintArc = Paint()
            paintArc.isAntiAlias = true

            //用于存放当前百分比的圆心角度
            var currentAngle = 0.0f
            val infoHeight = dataInfoPaint.textHeight
            val labelHeight =labelPaint.textHeight
            val textHeight = labelHeight + infoHeight
            for (cData in dataSet) {
                paintArc.color = cData.sliceColor
                if (CircleType.HALF == displayType) {
                    //setInitialAngle(180f)

                    //半圆， 宽应当是高的两倍
                    var hRadius: Float = this.width / 2f
                    var hCirY: Float = this.bottom
                    if (isShowBorder) {
                        hRadius -= this.borderWidth
                        hCirY -= this.borderWidth / 2
                    }
                    var oRadius = Math.round(Math.mul(hRadius, moRadius), 2)
                    var iRadius = Math.round(Math.mul(hRadius, miRadius), 2)
                    if (isShowInnerBG) //内部背景填充
                    {
                        drawPercent(canvas, bgCirclePaint, cirX, hCirY, hRadius, 180f, 180f)
                    } else {
                        iRadius = hRadius
                        oRadius = iRadius
                    }
                    if (isShowInnerFill) {
                        drawPercent(canvas, fillCirclePaint, cirX, hCirY, oRadius, 180f, 180f)
                    }


                    // float per = (float) cData.getPercentage();                    
                    //currentAngle = MathHelper.getInstance().round(MathExt.mul(180f, MathExt.div(per, 100f)),2);
                    currentAngle = Math.getSliceAngle(180f, cData.percentage.toFloat())
                    drawPercent(canvas, paintArc, cirX, hCirY, hRadius, 180f, currentAngle)
                    if (isShowInnerFill) //内部填充
                    {
                        drawPercent(canvas, fillCirclePaint, cirX, hCirY, iRadius, 180f, 180f)
                    }
                    if ("" !== cData.label) { //getCirY(hCirY,textHeight)
                        canvas.drawText(cData.label, cirX, Math.sub(hCirY, textHeight), labelPaint)
                    }
                    if ("" !== dataInfo)
                        canvas.drawText(dataInfo, cirX, hCirY - infoHeight, dataInfoPaint)
                } else {
                    currentAngle = Math.getSliceAngle(360f, cData.percentage.toFloat())
                    if (isShowInnerBG)
                        canvas.drawCircle(cirX, cirY, radius, bgCirclePaint)
                    // canvas.drawCircle(cirX, cirY, (float) (Math.round(radius * 0.9f)), mPaintFillCircle);
                    if (isShowInnerFill) {
                        val fillRadius = Math.round(Math.mul(radius, moRadius), 2)
                        canvas.drawCircle(cirX, cirY, fillRadius, fillCirclePaint)
                    }
                    canvas.drawArc(arcRF0, offsetAngle, currentAngle, true, paintArc)

                    //////////////////
                    if (isShowCap && (isShowInnerBG || isShowInnerFill)) {
                        val cap = Math.round(Math.mul(radius, miRadius), 2)
                        val capRadius = cap + (radius - cap) / 2

                        //箭头
                        if (isShowInnerBG) {
                            paintArc.color = bgCirclePaint.color
                        } else {
                            paintArc.color = fillCirclePaint.color
                        }
                        val pointBegin = Math.calcArcEndPointXY(cirX, cirY, capRadius, initOffsetAngle)
                        canvas.drawLine(cirX, cirY, pointBegin.x, pointBegin.y, paintArc)
                        canvas.drawCircle(pointBegin.x, pointBegin.y, (radius - cap) / 2, paintArc)

                        //箭头                    
                        val point = Math.calcArcEndPointXY(cirX, cirY, capRadius, Math.add(offsetAngle, currentAngle))
                        paintArc.color = cData.sliceColor
                        canvas.drawLine(cirX, cirY, point.x, point.y, paintArc)
                        canvas.drawCircle(point.x, point.y, (radius - cap) / 2, paintArc)
                    }
                    ////////////////////        	    	
                    if (isShowInnerFill)
                        canvas.drawCircle(cirX, cirY, Math.round(Math.mul(radius, miRadius), 2), fillCirclePaint)
                    if ("" !== cData.label)
                        canvas.drawText(cData.label, cirX, getCirY(cirY, labelHeight), labelPaint)
                    if ("" !== dataInfo)
                        canvas.drawText(dataInfo, cirX, Math.add(cirY, infoHeight), dataInfoPaint)
                }
                break
            }
        } catch (e: Exception) {
            Timber.d( e.toString())
        }
        return true
    }

   
    override fun renderBody(canvas: Canvas): Boolean {
        // 绘制图表
       super.renderBody(canvas)
       return drawPlot(canvas)
    }
    
    
}